package de.bloxel.controller;

import groovy.lang.GroovyShell;

import java.util.Collection;

import de.bloxel.ui.BloxelApplication;
import de.lessvoid.nifty.EndNotify;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.controls.console.controller.ConsoleCommandHandler;
import de.lessvoid.nifty.controls.console.controller.ConsoleControl;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.input.mapping.DefaultInputMapping;
import de.lessvoid.nifty.screen.KeyInputHandler;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;

public class HUDController implements ScreenController, KeyInputHandler {

  private static final GroovyShell SHELL = new GroovyShell();

  private Nifty nifty;
  private Screen screen;
  private boolean consoleVisible = false;
  private boolean allowConsoleToggle = true;

  private final BloxelConsoleAPI consoleAPI;

  public HUDController(final BloxelApplication theBloxelApplication) {
    consoleAPI = new BloxelConsoleAPI(theBloxelApplication);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void bind(final Nifty theNifty, final Screen theScreen) {
    nifty = theNifty;
    screen = theScreen;
    screen.addKeyboardInputHandler(new DefaultInputMapping(), this);
    final ConsoleControl control = nifty.createPopup("console-popup").findControl("console", ConsoleControl.class);
    control.output("Welcome to Bloxel!");
    control.output("Type 'help()' to get list of all available commands.");
    control.addCommandHandler(new ConsoleCommandHandler() {
      @Override
      public void execute(final String theString) {
        try {
          final Object result = SHELL.evaluate(String.format("bloxel.%s", theString));
          if (result != null) {
            if (result instanceof Collection<?>) {
              for (final Object resultItems : (Collection<?>) result) {
                control.output(resultItems.toString());
              }
            } else {
              control.output(result.toString());
            }
          }
        } catch (final Exception exception) {
          control.output(String.format("Unknown command: %s", theString));
        }
      }
    });
    SHELL.setVariable("bloxel", consoleAPI);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void onEndScreen() {
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void onStartScreen() {
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public boolean keyEvent(final NiftyInputEvent theNiftyInputEvent) {
    if (theNiftyInputEvent == NiftyInputEvent.ConsoleToggle) {
      toggleConsole();
      return true;
    }
    return false;
  }

  private void toggleConsole() {
    if (allowConsoleToggle) {
      allowConsoleToggle = false;
      if (consoleVisible) {
        closeConsole();
      } else {
        openConsole();
      }
    }
  }

  private void openConsole() {
    nifty.showPopup(screen, "console-popup", null);
    consoleVisible = true;
    allowConsoleToggle = true;
  }

  private void closeConsole() {
    nifty.closePopup("console-popup", new EndNotify() {
      @Override
      public void perform() {
        consoleVisible = false;
        allowConsoleToggle = true;
      }
    });
  }

}
